package com.aconcagua.factory {
  import com.aconcagua.beans.BeanDefinition;
  import com.aconcagua.beans.BeanDefinitionException;
  import com.aconcagua.beans.BeanDefinitionSupport;
  import com.aconcagua.beans.ConstructorArg;
  import com.aconcagua.beans.Property;
  import com.aconcagua.beans.Ref;
  import com.aconcagua.beans.Value;
  import com.aconcagua.dummy.DummyBean;
  import com.aconcagua.dummy.DummyBeanFactory;
  import com.aconcagua.dummy.DummyFactoryAwareBean;
  
  import flexunit.framework.TestCase;

  public class AbstractBeanFactoryTest extends TestCase {
    private var _beanFactory: AbstractBeanFactory;
    
    override public function setUp(): void {
      _beanFactory = new AbstractBeanFactory();
    }

    override public function tearDown():void {
      _beanFactory = null;
    }

    public function testRegisterBeanDefinitionWithNoType(): void {
      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(null);
      bean.name = "testBean"
      try {
        _beanFactory.registerBeanDefinition(bean);
        fail("Expected exception not thrown: BeanException"); 
      }
      catch(e: BeanDefinitionException) {
        //success!
      }
    }

    public function testRegisterSingletonDefinition(): void {
      const expectedType: Class = DummyBean;

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.scope = BeanDefinitionSupport.SCOPE_SINGLETON;
      bean.name = "dummyBean";
      
      _beanFactory.registerBeanDefinition(bean);
      this.assertGetSingletonBean(bean, expectedType);
    }
    
    public function testRegisterPrototypeDefinition(): void {
      const expectedType: Class = DummyBean;
      
      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.scope = BeanDefinitionSupport.SCOPE_PROTOTYPE;
      bean.name = "dummyBean";
      
      _beanFactory.registerBeanDefinition(bean);

      this.assertGetPrototypeBean(bean, expectedType);      
    }
    
    public function testAnonymousBean(): void {
      var anonymous: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      
      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "dummyBean";
      bean.addConstructorArg(new ConstructorArg(new Ref(anonymous)));
            
      _beanFactory.registerBeanDefinition(bean);
      assertNotNull(
        "Anonymous bean not injected", 
        DummyBean(
          _beanFactory.getBean(bean.name)
        ).constructorBean
      );
    }
/* 
    public function testDefaults(): void {
      fail("Test default is singleton, not-lazy, etc. etc.");
    }
 */
    /**
    * Test references to beans that have not been registered yet.
    **/ 
     public function testNotRegisteredReferences(): void {
      var constructorBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      constructorBean.name = "constructorBean";

      var propertyBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      propertyBean.name = "propertyBean";

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "dummyBean";
      bean.addConstructorArg(new ConstructorArg(new Ref(constructorBean)));
      bean.addProperty(new Property("propertyBean", new Ref(propertyBean)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      var constructorDummy: DummyBean = _beanFactory.getBean(constructorBean.name) as DummyBean;
      var propertyDummy: DummyBean = _beanFactory.getBean(propertyBean.name) as DummyBean;
      
      this.assertConstructorDependency(constructorDummy, dummyBean);
      this.assertPropertyDependency(propertyDummy, dummyBean);
    }

    public function testRegisteredReferences(): void {
      var constructorBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      constructorBean.name = "constructorBean";
      _beanFactory.registerBeanDefinition(constructorBean);

      var propertyBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      propertyBean.name = "propertyBean";
      _beanFactory.registerBeanDefinition(propertyBean);

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "dummyBean";
      bean.addConstructorArg(new ConstructorArg(new Ref(constructorBean)));
      bean.addProperty(new Property("propertyBean", new Ref(propertyBean)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      var constructorDummy: DummyBean = _beanFactory.getBean(constructorBean.name) as DummyBean;
      var propertyDummy: DummyBean = _beanFactory.getBean(propertyBean.name) as DummyBean;
      
      this.assertConstructorDependency(constructorDummy, dummyBean);
      this.assertPropertyDependency(propertyDummy, dummyBean);
    }

    public function testConstructorArgReference(): void {
      var referencedBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      referencedBean.name = "referencedBean";
      _beanFactory.registerBeanDefinition(referencedBean);

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "constructorBean";
      bean.addConstructorArg(new ConstructorArg(new Ref(referencedBean)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      
      var referencedDummy: DummyBean = _beanFactory.getBean(referencedBean.name) as DummyBean;
      this.assertConstructorDependency(referencedDummy, dummyBean);
    }

    public function testConstructorArgValue(): void {
      var dummyValue: DummyBean = new DummyBean();

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "constructorBean";
      bean.addConstructorArg(new ConstructorArg(new Value(dummyValue)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      
      this.assertConstructorDependency(dummyValue, dummyBean);
    }

    public function testSetPropertyReference(): void {
      var referencedBean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      referencedBean.name = "referencedBean";
      _beanFactory.registerBeanDefinition(referencedBean);

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "propertyBean";
      bean.addProperty(new Property("propertyBean", new Ref(referencedBean)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      var referencedDummy: DummyBean = _beanFactory.getBean(referencedBean.name) as DummyBean;

      this.assertPropertyDependency(referencedDummy, dummyBean);
    }

    public function testSetPropertyValue(): void {
      var dummyValue: DummyBean = new DummyBean();

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "propertyBean";
      bean.addProperty(new Property("propertyBean", new Value(dummyValue)));
      _beanFactory.registerBeanDefinition(bean);
      
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      
      this.assertPropertyDependency(dummyValue, dummyBean);
    } 
 
    public function testRegisterExistingBean(): void {
      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "propertyBean";
      _beanFactory.registerBeanDefinition(bean);
      try {
        _beanFactory.registerBeanDefinition(bean);
        fail("BeanDefinitionException was expected");
      }
      catch(e: BeanDefinitionException) {
        //success
      }
    }

     public function testPropertyPropertyCrossReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      beanA.addProperty(new Property("propertyBean", new Ref(beanB)));
      beanB.addProperty(new Property("propertyBean", new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanA);
      
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(aDummy, bDummy);
      this.assertPropertyDependency(bDummy, aDummy);
    } 
 

    /**
    * The constructor bean is registered before the property bean
    **/
     public function testConstructorPropertyCrossReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addProperty(new Property("propertyBean", new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanA);
      
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(aDummy, bDummy);
      this.assertConstructorDependency(bDummy, aDummy);
    } 

    /**
    * The constructor bean is registered before the property bean
    **/
     public function testIndirectConstructorPropertyCrossReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      var beanC: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanC.name = "beanC";

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanC)));
      beanC.addProperty(new Property("propertyBean", new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanA);
      
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;
      var cDummy: DummyBean = _beanFactory.getBean(beanC.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(aDummy, cDummy);
      this.assertConstructorDependency(bDummy, aDummy);
      this.assertConstructorDependency(cDummy, bDummy);
    } 

    /**
    * The constructor bean is registered before the property bean
    **/
     public function testComplexIndirectConstructorPropertyCrossReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      var beanC: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanC.name = "beanC";

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanC)));
      beanC.addProperty(new Property("propertyBean", new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanB);
      
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;
      var cDummy: DummyBean = _beanFactory.getBean(beanC.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(aDummy, cDummy);
      this.assertConstructorDependency(bDummy, aDummy);
      this.assertConstructorDependency(cDummy, bDummy);
    } 

    /**
    * The constructor bean is registered before the property bean. Lazy beans.
    **/
     public function testComplexIndirectConstructorPropertyCrossReferenceLazy(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";
      beanA.lazy = true;

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";
      beanB.lazy = true;

      var beanC: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanC.name = "beanC";
      beanC.lazy = true;

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanC)));
      beanC.addProperty(new Property("propertyBean", new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanB);
      
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var cDummy: DummyBean = _beanFactory.getBean(beanC.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(aDummy, cDummy);
      this.assertConstructorDependency(bDummy, aDummy);
      this.assertConstructorDependency(cDummy, bDummy);
    } 

    public function testPropertyConstructorCrossReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      beanA.addProperty(new Property("propertyBean", new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanA)));

      _beanFactory.registerBeanDefinition(beanA);
      
      var aDummy: DummyBean = _beanFactory.getBean(beanA.name) as DummyBean;
      var bDummy: DummyBean = _beanFactory.getBean(beanB.name) as DummyBean;

      //Asserts
      this.assertPropertyDependency(bDummy, aDummy);
      this.assertConstructorDependency(aDummy, bDummy);
    } 
       
    public function testCircularReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanA)));

      try {
        _beanFactory.registerBeanDefinition(beanA);
        fail("BeanCreationException was expected");
      }
      catch(e: BeanCreationException) {
        //success
      }
    }

    public function testIndirectCircularReference(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";

      var beanC: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanC.name = "beanC";

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanC)));
      beanC.addConstructorArg(new ConstructorArg(new Ref(beanA)));

      try {
        _beanFactory.registerBeanDefinition(beanA);
        fail("BeanCreationException was expected");
      }
      catch(e: BeanCreationException) {
        //success
      }
    }

    public function testCircularReferencePrototypes(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";
      beanA.scope = BeanDefinitionSupport.SCOPE_PROTOTYPE;

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";
      beanB.scope = BeanDefinitionSupport.SCOPE_PROTOTYPE;

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanA)));

      try {
        _beanFactory.registerBeanDefinition(beanA);
        _beanFactory.registerBeanDefinition(beanB);

        _beanFactory.getBean(beanA.name);
        fail("BeanCreationException was expected");
      }
      catch(e: BeanCreationException) {
        //success
      }
    }


    public function testCircularReferencePrototypesUnregistered(): void {
      var beanA: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanA.name = "beanA";
      beanA.scope = BeanDefinitionSupport.SCOPE_PROTOTYPE;

      var beanB: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      beanB.name = "beanB";
      beanB.scope = BeanDefinitionSupport.SCOPE_PROTOTYPE;

      beanA.addConstructorArg(new ConstructorArg(new Ref(beanB)));
      beanB.addConstructorArg(new ConstructorArg(new Ref(beanA)));

      try {
        _beanFactory.registerBeanDefinition(beanA);

        _beanFactory.getBean(beanA.name);
        fail("BeanCreationException was expected");
      }
      catch(e: BeanCreationException) {
        //success
      }
    }
    
    public function testEagerBean(): void {
      var dummyValue: DummyBean = new DummyBean();

      var bean: MockBean = new MockBean(DummyBean);
      bean.name = "dummyBean";
      bean.lazy = false;
      _beanFactory.registerBeanDefinition(bean);

      assertTrue("Lazy bean has not been instantiated", bean.isInstantiated);
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
    }
    
    public function testLazyBean(): void {
      var dummyValue: DummyBean = new DummyBean();

      var bean: MockBean = new MockBean(DummyBean);
      bean.name = "dummyBean";
      bean.lazy = true;
      _beanFactory.registerBeanDefinition(bean);

      assertFalse("Lazy bean has been instantiated eagerly", bean.isInstantiated);
      var dummyBean: DummyBean = _beanFactory.getBean(bean.name);
      assertTrue("Lazy bean has not been instantiated", bean.isInstantiated);
    }
 
    public function testAlias(): void {
      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBean);
      bean.name = "dummyBean";

      _beanFactory.registerAlias("alias1", bean);
      _beanFactory.registerBeanDefinition(bean);
      _beanFactory.registerAlias("alias2", bean);
      
      var aliases: Array = _beanFactory.getAliases(bean.name);
      assertEquals("Two aliases were expected", 2, aliases.length);
      assertTrue("alias1 not found", aliases[0] == "alias1" || aliases[1] == "alias1");
      assertTrue("alias2 not found", aliases[0] == "alias2" || aliases[1] == "alias2");
      
      var alias1Bean: DummyBean = _beanFactory.getBean("alias1");
      var alias2Bean: DummyBean = _beanFactory.getBean("alias2");
      var dummy: DummyBean = _beanFactory.getBean(bean.name);
      
      assertEquals("pre-defined alias is different to the singleton instance", dummy, alias1Bean);
      assertEquals("post-defined alias is different to the singleton instance", dummy, alias2Bean);
    }
    
    public function testRegisterBeanFactoryAwareBean(): void {
      const expectedType: Class = DummyFactoryAwareBean;

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyFactoryAwareBean);
      bean.name = "factoryAwareBean";
      
      _beanFactory.registerBeanDefinition(bean);

      this.assertGetSingletonBean(bean, expectedType);
      assertTrue(
        "BeanFactory not injected", 
        DummyFactoryAwareBean(_beanFactory.getBean(bean.name))
          .verifyBeanFactory(_beanFactory)
      );
    }

    public function testRegisterFactoryBean(): void {
      const expectedType: Class = DummyBean;

      var bean: BeanDefinitionSupport = new BeanDefinitionSupport(DummyBeanFactory);
      bean.scope = BeanDefinitionSupport.SCOPE_SINGLETON;
      bean.name = "dummyFactory";

      _beanFactory.registerBeanDefinition(bean);

      this.assertSingletonDefinition(bean);
      assertTrue(
        "BeanDefinitionSupport is not " + bean.type, 
        _beanFactory.getBean(bean.name) is expectedType
      );

      //This is just because the factory bean creates new instances every time. 
      //But the factory bean is a singleton indeed.
      this.assertPrototypeBean(bean);  
    }

    private function assertGetSingletonBean(bean: BeanDefinition, expectedType: Class): void {
      this.assertSingletonDefinition(bean);
      this.assertSingletonBean(bean);
      assertTrue("BeanDefinitionSupport is not " + bean.type, _beanFactory.getBean(bean.name) is expectedType);
    }

    private function assertSingletonDefinition(bean: BeanDefinition): void {
      assertTrue("Factory does not contains bean: " + bean.name, _beanFactory.containsBean(bean.name));
      assertTrue("Definition is not singleton", _beanFactory.isSingleton(bean.name));
      assertTrue("Definition does not matches type " + bean.type, _beanFactory.isTypeMatch(bean.name, bean.type));
      assertFalse("Definition is prototype", _beanFactory.isPrototype(bean.name));
      assertNotNull("BeanDefinitionSupport is null", _beanFactory.getBean(bean.name));
      assertNotUndefined("BeanDefinitionSupport is undefined", _beanFactory.getBean(bean.name));
    }

    private function assertSingletonBean(bean: BeanDefinition): void {
      assertEquals("Equals failed. Not a singleton??", _beanFactory.getBean(bean.name), _beanFactory.getBean(bean.name));
      assertStrictlyEquals("Strict Equals failed. Not a singleton??", _beanFactory.getBean(bean.name), _beanFactory.getBean(bean.name));
    }

    private function assertGetPrototypeBean(bean: BeanDefinition, expectedType: Class): void {
      this.assertPrototypeDefinition(bean);
      this.assertPrototypeBean(bean);
      assertTrue("BeanDefinitionSupport is not " + bean.type, _beanFactory.getBean(bean.name) is expectedType);
    }

    private function assertPrototypeDefinition(bean: BeanDefinition): void {
      assertTrue("Factory does not contains bean: " + bean.name, _beanFactory.containsBean(bean.name));
      assertFalse("Definition is singleton", _beanFactory.isSingleton(bean.name));
      assertTrue("Definition does not matches type " + bean.type, _beanFactory.isTypeMatch(bean.name, bean.type));
      assertTrue("Definition is not prototype", _beanFactory.isPrototype(bean.name));
      assertNotNull("BeanDefinitionSupport is null", _beanFactory.getBean(bean.name));
      assertNotUndefined("BeanDefinitionSupport is undefined", _beanFactory.getBean(bean.name));
    }

    private function assertPrototypeBean(bean: BeanDefinition): void {
      assertFalse("Equals failed. Singleton??", _beanFactory.getBean(bean.name) == _beanFactory.getBean(bean.name));
      assertFalse("Strict Equals failed. Singleton??", _beanFactory.getBean(bean.name) === _beanFactory.getBean(bean.name));
    }

    private function assertPropertyDependency(propertyDummy: DummyBean, dummyBean: DummyBean): void {
      assertNotNull("Property bean is null", propertyDummy);
      assertNotUndefined("Property bean is undefined", propertyDummy)
      assertEquals("Property injected bean is invalid in bean ", propertyDummy, dummyBean.propertyBean);
      assertStrictlyEquals("Property injected bean is invalid", propertyDummy, dummyBean.propertyBean);
    }

    private function assertConstructorDependency(constructorDummy: DummyBean, dummyBean: DummyBean): void {
      assertNotNull("Constructor bean is null", constructorDummy);
      assertNotUndefined("Constructor bean is undefined", constructorDummy)
      assertEquals("Constructor injected bean is invalid", constructorDummy, dummyBean.constructorBean);
      assertStrictlyEquals("Constructor injected bean is invalid", constructorDummy, dummyBean.constructorBean);
    }
  }
}

/********** INTERNAL DEFINITIONS. Mock classes *********/
import com.aconcagua.beans.BeanDefinitionSupport;
import com.aconcagua.factory.BeanFactory;
import com.aconcagua.factory.BeanFactoryAware;

internal class MockBean extends BeanDefinitionSupport {
  private var _registered: Boolean = false;
  private var _instantiated: Boolean = false;
  
  public function MockBean(type: Class) {
    super(type);
  } 
  
  override public function createInstance(factory:BeanFactory):Object {
    var instance: Object = super.createInstance(factory);
    _instantiated = true;
    return instance;
  }
   
  public function get isRegistered(): Boolean {
    return _registered;
  }
  
  public function get isInstantiated(): Boolean {
    return _instantiated;
  }
}
